﻿#pragma once
#include "LuaCommon.h"
#include "LuaObject.h"
#include "LuaStackOps.h"

class LUAOBJ_API LuaTable :public LuaObject
{
public:
	LuaTable();
	LuaTable(LuaState* L);
	LuaTable(LuaObjectImpl* impl);
	LuaTable(const LuaObject& rfs);
	LuaTable(const LuaTable& rfs);

	//判断是否是lua表
	bool isValid() const;

	//lua表操作
	LuaObject getTable(const char* key);
	LuaObject getTable(lua_Integer idx);
	LuaObject getTable(void* key);
	LuaObject getTable(const std::string& key);

	LuaObject rawGetTable(const char* key);
	LuaObject rawGetTable(lua_Integer idx);
	LuaObject rawGetTable(void* key);
	LuaObject rawGetTable(const std::string& key);


	LuaObject operator[](const char* key) {
		return getTable(key);
	}

	LuaObject operator[](lua_Integer key) {
		return getTable(key);
	}

	LuaObject operator[](void* key) {
		return getTable(key);
	}

	bool setTable(void* key, LuaObject val);
	bool setTable(const char* key,LuaObject val);
	bool setTable(lua_Integer key,LuaObject val);

	bool rawSetTable(void* key, LuaObject val);
	bool rawSetTable(const char* key, LuaObject val);
	bool rawSetTable(lua_Integer key, LuaObject val);

	//设置常量
	bool setConst(LuaConstDef* tag);

	inline size_t count()const{return objLen();}

	template<class T>
	bool setTable(const char* key,T val)
	{
		if(isValid())
		{
			lua_State* L=getLuaState();
			lua_pushstring(L,key);//key
			StackOps::Push(L,val);
			lua_settable(L,getIndex());
			return true;
		}
		return false;
	}

	template<class T>
	bool setTable(lua_Integer key,T val)
	{
		if(isValid())
		{
			lua_State* L=getLuaState();
			lua_pushinteger(L,key);//key
			StackOps::Push(L,val);
			lua_settable(L,getIndex());
			return true;
		}
		return false;	
	}

	template<class T>
	bool rawSetTable(const char* key, T val)
	{
		if (isValid())
		{
			lua_State* L = getLuaState();
			lua_pushstring(L, key);//key
			StackOps::Push(L, val);
			lua_rawset(L, getIndex());
			return true;
		}
		return false;
	}

	template<class T>
	bool rawSetTable(lua_Integer key, T val)
	{
		if (isValid())
		{
			lua_State* L = getLuaState();
			lua_pushinteger(L, key);//key
			StackOps::Push(L, val);
			lua_rawset(L, getIndex());
			return true;
		}
		return false;
	}


	class ArrayIterator {
	public:
		ArrayIterator(LuaObject ltab, size_t index)
			:m_table(ltab), m_index(index)
		{
		}

		size_t index() { return m_index; }
		LuaObject value();
		LuaObject operator*() { return value(); }

		bool operator!=(const ArrayIterator& rfs) {
			return m_index != rfs.m_index;
		}

		bool operator==(const ArrayIterator& rfs) {
			return m_index == rfs.m_index;
		}

		void operator++() {
			++m_index;
		}

	private:
		LuaObject m_table;
		size_t m_index;
	};

	ArrayIterator arrayBegin();
	ArrayIterator arrayEnd();


	//迭代器
	class Iterator
	{
	public:
		Iterator();
		Iterator(LuaObject ltab);

		//注意不要对key直接调用toString，有数字索引时会导致遍历出错
		LuaObject key() { return m_key; }
		LuaObject value() { return m_value; }
		LuaObject operator*() {return m_value;}

		bool operator!=(const Iterator& rfs);
		bool operator==(const Iterator& rfs);
		bool operator++();
		bool isValid()const;


	private:
		LuaObject m_table;
		LuaObject m_key;
		LuaObject m_value;
		bool m_valid;
	};

	Iterator begin();
	Iterator end();
};

